/*-
 * MessageFormat.java
 *
 * Copyright (c) 2007, Stein Gunnar Bakkeby
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Stein Gunnar Bakkeby nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.googlecode.attention.at;

/**
 * AT+CMGF Select SMS message format.
 * 
 * Test command                 Response
 * AT+CMGF=?                    +CMGF: (list of supported <mode>s) OK
 * 
 * Read command                 Response
 * AT+CMGF?                     +CMGF: <mode> OK
 * 
 * Write command                Response
 * AT+CMGF = [<mode>]           TA sets parameter which specifies the input
 *                              and output format of messages to be used.
 *                              OK
 * Parameter
 * <mode> 0 PDUEntry mode
 *        1 text mode
 *                              
 * Reference
 * GSM 07.05
 *
 * @author Stein Gunnar Bakkeby
 */
public class MessageFormat extends AtCommand<MessageFormat> {
  
  private static Mode[] supportedModes = new Mode[] { Mode.UNKNOWN };
  private static Mode currentMode = Mode.UNKNOWN;
  
  /**
   * Message mode enum, represents the message format when sending
   * and receiving AT commands.
   *
  
   * @author Stein Gunnar Bakkeby
   */
  public enum Mode {
    /** PDUEntry mode */
    PDU('0'),
    /** Text mode */
    TEXT('1'),
    /** Unknown mode */
    UNKNOWN('U');
    
    private char value;
    private Mode(char value) {
      this.value = value;
    }
    
    /**
     * This will return the respective mode based
     * on a given integer or a char.
     * 
     * @param value Integer values 0 or 1, or char values '0' or '1'
     * @return PDUEntry if 0 or '0', TEXT if 1 or '1', or UNKNOWN otherwise 
     */
    public static Mode getMode(char value) {
      switch (value) {
      case '0':
        return PDU;
        
      case '1':
        return TEXT;
        
      default:
        return UNKNOWN;
      }
    }

    /**
     * This will return the enums value.
     *  
     * @return '0' or '1', or 'U' if unknown
     */
    public char getValue() {
      return value;
    }
  }
  
  public MessageFormat(final AtListener<MessageFormat> listener) {
    super(listener);
  }
  
  /** Lists supported modes. */
  public void prepareTest() {
    setCommand("AT+CMGF=?", Command.TEST);
  }
  
  /** Retrieves the current mode. */
  public void prepareRead() {
    setCommand("AT+CMGF?", Command.READ);
  }
  
  /**
   * Sets a specific mode.
   * 
   * @param mode The mode to set
   */
  public void prepareWrite(Mode mode) {
    setCommand("AT+CMGF=" + mode.getValue(), Command.WRITE);
  }
  
  @Override
  protected void parseTest(final String response) {
    if (success) {
      /* Response on the format of: +CMGF: (list of supported <mode>s) OK */
      final String resp = removeCRLF(response);
      final int firstIndex = resp.indexOf('(');
      final int lastIndex = resp.lastIndexOf(')');
      if (lastIndex - firstIndex > 2) {
        final String data = resp.substring(firstIndex + 1, lastIndex);
        /* Ignoring range as only two types */
        final String[] values = data.split(",");
        final int length = values.length;
        supportedModes = new Mode[length];
        for (int i = 0; i < length; i++) {
          supportedModes[i] = values[i].length() > 0 ? Mode.getMode(values[i].charAt(0)) : Mode.UNKNOWN;
        }
      } else {
        supportedModes = new Mode[] { Mode.UNKNOWN };
      }
    }
  }
  
  @Override
  protected void parseRead(String response) {
    if (success) {
      /* Response on the format of: +CMGF: <mode> OK */
      final String resp = removeCRLF(response);
      final int firstIndex = resp.indexOf("+CMGF:") + 6;
      final int lastIndex = resp.indexOf("OK");
      if (lastIndex - firstIndex > 2) {
        final String data = resp.substring(firstIndex, lastIndex).trim();
        currentMode = Mode.getMode(data.charAt(0));
      } else {
        currentMode = Mode.UNKNOWN;
      }
    }
  }
  
  @Override
  protected void parseWrite(String response) {
    /* Nothing to do, as success/failure is handled elsewhere. */
  }
  
  /**
   * This will return a list of the supported modes.
   * 
   * @return A list of Mode enums
   */
  public static Mode[] getSupportedModes() {
    return supportedModes;
  }
  
  /**
   * This will return the current mode.
   * 
   * @return A Mode enum
   */
  public static Mode getCurrentMode() {
    return currentMode;
  }
  

  @Override
  protected MessageFormat getThis() {
    return this;
  }
}
